package benchmarks.tpch.mongo.queries;

import api.Configuration;
import api.connection.ConnectionMongo;
import api.connection.DBConnection;
import api.result.Result;
import com.mongodb.*;
import com.mongodb.client.*;
import org.bson.BsonDocument;
import org.bson.Document;

import java.util.ArrayList;
import java.util.Date;
import java.util.regex.Pattern;

public class Q20Mongo extends GenericQueryMongo {
    public static final String queryName = "Q20";

    public Q20Mongo(){
        super.queryName = queryName;
    }

    private static String queryPart = "{ " +
            "\"shipdate\" : { \"$gte\" : new Date(1994, 0, 1), \"$lt\" : new Date(1995, 0, 1) }, " +
            "\"partsupp.supplier.nation.name\" : { $regex : '^CANADA'}, " +
            "\"partsupp.part.name\" : { $regex : '^forest', $options : 'i' } " +
            "}";

    private static String calculateMatchStringQuery = "{ $match : " +
            queryPart +
            "}";

    private static String calculateGroupStringQuery = "{ $group : {" +
            "_id : null, " +
            "sum_quantity : { $sum : \"$quantity\"}" +
            "}}";

    public Result run(DBConnection dbConnection) {
        ConnectionMongo connectionMongo = (ConnectionMongo)dbConnection;
        MongoClient mongoClient = connectionMongo.makeConnection();
        MongoDatabase database = mongoClient.getDatabase("tpch");
        ArrayList<BsonDocument> caculateAggregate = new ArrayList<>();
        caculateAggregate.add(BsonDocument.parse(calculateMatchStringQuery));
        caculateAggregate.add(BsonDocument.parse(calculateGroupStringQuery));
        AggregateIterable<Document> result = database.getCollection("deals").aggregate(caculateAggregate);
        MongoCursor<Document> iterator = result.iterator();
        ArrayList<Document> results = new ArrayList<>();
        while (iterator.hasNext()) {
            results.add(iterator.next());
        }
        double half_total_quantity = results.get(0).getDouble("sum_quantity") / 2.0;
        String findStringQuery = "{ \"$and\" : [ " +
                queryPart +
                ", " +
                "{\"partsupp.availqty\" : { \"$gt\" : " +
                 half_total_quantity +
                "} } ]}";
        BsonDocument projectClass = BsonDocument.parse("{\"_id\" : 0, \"partsupp.supplier.name\" : 1, \"partsupp.supplier.address\" : 1}");
        BsonDocument sortQuery = BsonDocument.parse("{\"partsupp.supplier.name\" : 1}");
        FindIterable<Document> resultF = database.getCollection("deals")
                .find(BsonDocument.parse(findStringQuery)).projection(projectClass).sort(sortQuery);
        iterator = resultF.iterator();
        results = new ArrayList<>();
        while (iterator.hasNext()) {
            results.add(iterator.next());
        }
        return null;
    }

//    @Override
//    public Result run(DBConnection dbConnection){
//        Date date = new Date(94,0,1);
//        String nationName = "CANADA";
//        String colorName = "forest";
//
//        MongoClient mongoClient = (MongoClient)dbConnection.makeConnection();
//        DB db = mongoClient.getDB("tpch");
//
//        DBCollection collection = db.getCollection("deals");
//
//        BasicDBObject key = new BasicDBObject("sum_quantity", true);
//
//        BasicDBObject query = new BasicDBObject();
//
//        BasicDBObject dateRange = new BasicDBObject();
//        dateRange.append("$gte", date)
//                .append("$lt", new Date(date.getYear()+1, date.getMonth(), date.getDate()));
//
//        Pattern nation = Pattern.compile("^" + nationName);
//        Pattern color = Pattern.compile("^" + colorName);
//
//        query.append("shipdate", dateRange)
//                .append("partsupp.supplier.nation.name", new BasicDBObject("$regex", nation))
//                .append("partsupp.part.name", new BasicDBObject("$regex", color));
//
//        BasicDBObject initial = new BasicDBObject("sum", 0);
//
//        String reduce = "function(doc, out){"
//                + "out.sum = (out.sum + doc.quantity) / 2;"
//                +"}";
//
//        BasicDBList groupList = (BasicDBList)collection.group(key, query, initial, reduce, null);
//        Object halfTotalQuantity = ((BasicDBObject) groupList.get(0)).get("sum");
//
//        query.append("partsupp.availqty", new BasicDBObject ("$gt", halfTotalQuantity));
//        BasicDBObject projection = new BasicDBObject();
//        projection.append("_id", 0).append("partsupp.supplier.name", 1).append("partsupp.supplier.address", 1);
//
//        MongoDatabase dbM = mongoClient.getDatabase("tpch");
//        MongoCollection collectionM= dbM.getCollection("deals");
//
//        FindIterable<Document> docs = collectionM.find(query)
//                .sort(new BasicDBObject("partsupp.supplier.name",1))
//                .projection(projection);
//
//        /*MongoCursor<Document> cursor = docs.iterator();
//        while(cursor.hasNext()){
//            Document doc = cursor.next();
//            System.out.println(doc.toJson());
//        }*/
//        return null;
//    }

    private static class TestQ20{
        public static void main(String[] args){
            Configuration config = new Configuration();
            config.setBenchmark("tpch");
            config.setDb_username("root");
            config.setDb_password("123456");
            Q20Mongo q20Mongo = new Q20Mongo();
            DBConnection dbConnection =new ConnectionMongo(config);
            q20Mongo.run(dbConnection);
        }
    }
}